<?php

namespace humhub\modules\api\controllers;

use humhub\modules\api\models\Group;
use humhub\modules\api\models\GroupUser;
use humhub\modules\user\models\User;
use Yii;
use yii\filters\auth\CompositeAuth;
use yii\filters\auth\HttpBearerAuth;
use humhub\modules\api\models\FileAli;

/**
 * 融云群组功能实现
 */
class GroupController extends Base4Controller
{

    private $ry;
    const KEY = 'cpj2xarlc44on';
    const SECRET = '5BQvu2GBBi';


    public function init()
    {
        parent::init();
        $dir     = explode('protected', dirname(__FILE__));
        $alifile = $dir[0] . '/protected/vendor/rongyun/rongcloud.php';
        if (is_file($alifile)) {
            include_once $alifile;
        } else {
            return false;
        }
        $this->ry = new \RongCloud(self::KEY, self::SECRET);
    }

    /**
     * @inheritdoc
     */
    public function behaviors()
    {
        $behaviors                  = parent::behaviors();
        $behaviors['authenticator'] = [
            'class'       => CompositeAuth::className(),
            'authMethods' => [
                //QueryParamAuth::className(),
                HttpBearerAuth::className(),
            ],
        ];

        return $behaviors;
    }

    /**
     * 创建群组方法（创建群组，并将用户加入该群组，用户将可以收到该群的消息，同一用户最多可加入 500 个群，每个群最大至 3000 人，App 内的群组数量没有限制.
     *
     * post api/group/create
     *
     * post.guid:用户 guid。（必传）
     *
     * post.groupName:群组的名称。（必传）
     *
     * post.files 图片文件
     *
     * post.des:群描述
     *
     * @return int 群组id 失败返回false
     **/
    public function actionCreate()
    {
        $data = Yii::$app->request->post();
        if ($data['guid'] == '' or $data['groupName'] == '') {
            throw new \yii\web\BadRequestHttpException('数据有误，请重新提交');
        }
        $guid      = $data['guid'];
        $uid       = Yii::$app->user->id;
        $groupName = $data['groupName'];
        if (isset($data['des'])) {
            $des = $data['des'];
        } else {
            $des = '';
        }
        $group = new Group();

        $files = \yii\web\UploadedFile::getInstancesByName('files');

        $group->guid      = $guid;
        $group->uid       = $uid;
        $group->des       = $des;
        $group->name      = $groupName;
        $group->time      = date('Y-m-d H:i:s', time());
        $group->update_at = date('Y-m-d H:i:s', time());
        $group->save();

        $groupId = $group->attributes['id'];
        $gid     = (string)$groupId;

        if (!isset($files[0])) {
            $url = 'http://www.uni-class.com/img/group.jpg';
        } else {
            $img = $files[0];

            $profileImage = new \humhub\libs\ProfileImage($gid);

            $f = $this->handleFileUpload($img, $group, $gid, 'cover');

            if ($f !== false) {
                $url = $profileImage->getUrl();
            } else {
                throw new \yii\web\BadRequestHttpException('上传文件失败');
            }
        }

        $gro      = Group::findOne($groupId);
        $gro->img = $url;
        $gro->save(false);

        $gu         = new GroupUser();
        $gu->gid    = $groupId;
        $gu->uid    = $uid;
        $gu->guid   = $guid;
        $gu->status = 1;
        $gu->save();

        $data = $this->ry->group()->create($guid, $groupId, $groupName);
        $data = json_decode($data, true);
        if ($data['code'] == 200) {
            return ['groupId' => $groupId];
        } else {
            return false;
        }
    }

    /**
     * 获取组内所有成员id
     *
     * get api/group/get-user
     *
     * get. gid:群组id（必传）
     *
     * @return array 用户信息及用户总数
     **/
    public function actionGetUser()
    {
        $gid = Yii::$app->request->get('gid');
        if (!$gid) {
            throw new \yii\web\BadRequestHttpException('ID不存在');
        }
        $pages = new \yii\data\Pagination([
            'defaultPageSize' => 10,
            'validatePage'    => false,
        ]);

        $count = GroupUser::find()->where(['gid'=>$gid,'status'=>1])->count();

        $model = GroupUser::find()
            ->select('guid')
            ->where(['gid'=>$gid,'status'=>1])
            ->offset($pages->offset)
            ->limit($pages->limit)
            ->all();

        foreach ($model as $k => $v) {
            $user['user'][] = $this->getProfile($v['guid']);
        }
        $user['count'] = $count;
        return $user;
    }

    //同步当前用户所属群组方法（当第一次连接融云服务器时，需要向融云服务器提交 userId 对应的用户当前所加入的所有群组，此接口主要为防止应用中用户群信息同融云已知的用户所属群信息不同步。）
    private function sync()
    {
        $uid  = Yii::$app->user->id;
        $guid = Yii::$app->user->guid;
        if (!$uid) {
            throw new \yii\web\BadRequestHttpException('请先登录');
        }
        $data = GroupUser::find()->select('gid')->where(['uid' => $uid, 'status' => 1])->groupBy('gid')->asArray()->all();
        if ($data) {
            foreach ($data as $v) {
                $gid         = $v['gid'];
                $gu          = Group::findOne($gid);
                $group[$gid] = $gu->name;
            }
            $data = $this->ry->group()->sync($guid, $group);
            $data = json_decode($data, true);
            if ($data['code'] == 200) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }

    }

    /**
     * 编辑保存群组信息方法
     *
     * post api/group/refresh
     *
     * post.gid:群组 Id。（必传）
     *
     * post.groupName:群名称。（必传）未更改内容传回旧值
     *
     * post.files  图片文件
     *
     * post.des:群描述。
     *
     * @return boolean
     **/
    public function actionRefresh()
    {
        $data = Yii::$app->request->post();
        if ($data['groupName'] == '' or $data['gid'] == '') {
            throw new \yii\web\BadRequestHttpException('数据有误');
        }
        $name = $data['groupName'];
        $gid  = (string)$data['gid'];
        if (isset($data['des'])) {
            $des = $data['des'];
        } else {
            $des = '';
        }

        $group = Group::findOne($gid);

        $files = \yii\web\UploadedFile::getInstancesByName('files');

        if (!$files) {
            $img = $group->img;
        } else {
            $img = $files[0];
        }
        if ($group->img == $img) {
            $logo = $group->img;
        } else {
            $profileImage = new \humhub\libs\ProfileImage($gid);

            $f = $this->handleFileUpload($img, $group, $gid, 'cover');
            if ($f !== false) {
                $logo = $f['url'] . '?m=' . time();
            } else {
                throw new \yii\web\BadRequestHttpException('上传文件失败');
            }
        }

        $group->name      = $name;
        $group->update_at = date('Y-m-d H:i:s', time());
        $group->des       = $des;
        $group->img       = $logo;
        $group->save(false);

        $res = $this->ry->group()->refresh($gid, $name);
        $res = json_decode($res, true);
        if ($res['code'] == 200) {
            return true;
        } else {
            return false;
        }

    }

    /**
     * 将用户加入指定群组，用户将可以收到该群的消息，同一用户最多可加入 500 个群，每个群最大至 3000 人。
     *
     * get api/group/join
     *
     * get.guid:要加入群的用户guid. 多个guid以 ，进行拼接（必传）
     *
     * get.gid:要加入的群 Id。（必传）
     *
     * @return boolean
     **/
    public function actionJoin()
    {
        $data = Yii::$app->request->get();
        $gid  = $data['gid'];
        if (!$gid) return false;
        $groupName = Group::findOne($gid)->name;
        $uids      = explode(',', $data['guid']);
        $uids      = array_filter($uids);
        $ug        = new GroupUser();
        foreach ($uids as $v) {
            $u_g  = clone $ug;
            $this->send($gid,$v,1);
            $user = User::findOne(['guid' => $v]);
            $uid  = $user->id;
            $pd   = GroupUser::find()->where(['gid' => $gid, 'uid' => $uid])->one();
            if ($pd == '') {
                $u_g->guid   = $v;
                $u_g->uid    = $uid;
                $u_g->gid    = $gid;
                $u_g->status = 1;
                $u_g->save();
            } else {
                $pd->status = 1;
                $pd->save();
            }
        }

        $res = $this->ry->group()->join($uids, $gid, $groupName);
        $res = json_decode($res, true);
        if ($res['code'] == 200) {
            return true;
        } else {
            return false;
        }

    }

    /**
     * 退出群组方法（将用户从群中移除，不再接收该群组的消息.）
     *
     * get api/group/quit
     *
     * get.guid:要退出群的用户 guid.（必传）
     *
     * get.gid:要退出的群 Id.（必传）
     *
     * @return boolean
     **/
    public function actionQuit()
    {
        $data = Yii::$app->request->get();
        $guid = $data['guid'];
        $gid  = $data['gid'];
        $ug   = GroupUser::find()->where(['guid' => $guid, 'gid' => $gid])->one();
        $ug->delete();
        $this->send($gid,$guid,2);
        $res = $this->ry->group()->quit($guid, $gid);

        $res = json_decode($res, true);
        if ($res['code'] == 200) {
            $this->sync();
            return true;
        } else {
            return false;
        }

    }

    /**
     * 解散群组方法。（将该群解散，所有用户都无法再接收该群的消息。）
     *
     * get api/group/dismiss
     *
     * get.guid:操作解散群的用户 guid。（必传）
     *
     * get.gid:要解散的群 Id。（必传）
     *
     * @return boolean
     **/
    public function actionDismiss()
    {
        $data = Yii::$app->request->get();

        if ($data['gid']) {
            $group = Group::findOne($data['gid']);
            if (!$group) {
                throw new \yii\web\BadRequestHttpException('数据有误,或已删除');
            }
        } else {
            throw new \yii\web\BadRequestHttpException('数据有误');
        }
        if ($data['guid'] != $group->guid) {
            throw new \yii\web\BadRequestHttpException('非群主无权解散本群');
        }

        $gid  = $data['gid'];
        $guid = $data['guid'];
        $da = GroupUser::find()->where(['gid' => $gid, 'status' => 1])->all();
        if ($da) {
            foreach ($da as $v) {
                $gd         = $v['guid'];
                $this->ry->group()->quit($gd, $gid);
            }
        }
        Group::deleteAll(['id' => $gid]);
        GroupUser::deleteAll(['gid' => $gid]);
        $res = $this->ry->group()->dismiss($guid, $gid);

        $res = json_decode($res, true);
        if ($res['code'] == 200) {
            $group->delete();
            return true;
        } else {
            return false;
        }
    }

    /**
     * 获取群的相关资料
     *
     * get api/group/info
     *
     * get.gid:群 Id。（必传）
     *
     * @return array 群资料 id：群id  name：群名称  uid：群主id  gid：群主guid  des：群描述  img：群logo  time：创建时间  gid无效返回为空
     **/
    public function actionInfo()
    {
        $gid = Yii::$app->request->get('gid');
        if ($gid) {
            $pd=Group::findOne($gid);
            if ($pd){
                $data = $this->getInfo($gid);
                return $data;
            }else{

            }
        }else{
            return [];
        }

    }

    /**
     * 搜索群
     *
     * get api/group/search
     *
     * get.key  key:搜索内容（必传）
     *
     * 默认每页10条数据，分页结果同评论接口 /api/comment
     *
     * @return array  id：群id  name：群名称  uid：群主id  gid：群主guid  des：群描述  img：群logo  time：创建时间  （status 0未加入 1已加入 2申请中）  gid无效返回为 空
     **/
    public function actionSearch()
    {
        $key  = Yii::$app->request->get("key", '');
        $key =trim($key);
        $post = Group::find();
        if ($key) {
            $post->andFilterWhere(['like', 'name', $key])
                ->orFilterWhere(['like', 'des', $key]);
        }
        $pages = new \yii\data\Pagination([
            'defaultPageSize' => 10,
            'validatePage'    => false,
        ]);
        $model = $post->offset($pages->offset)->limit($pages->limit)->all();

        $data = [];
        if ($model) {
            foreach ($model as $k => $item) {
                $gid    = $item->id;
                $data[] = $this->getInfo($gid);
            }
        }
        return $data;
    }

    /**
     * 获取推荐群组列表
     *
     * get api/group/hot
     *
     * get.limit 获取数量 默认 10
     *
     * @return array id：群id  name：群名称  uid：群主id  gid：群主guid  des：群描述  img：群logo  （status 0未加入 1已加入 2申请中）  time：创建时间  无数据返回为空
     **/
    public function actionHot()
    {
        $limit = (int)Yii::$app->request->get('limit');
        if (!$limit) $limit = 10;
        $data = GroupUser::findBySql("select count(*) as total,gid from user_group group by gid order by total DESC,gid ASC limit " . $limit)->all();
        $gr   = [];
        if ($data) {
            foreach ($data as $v) {
                $gid  = $v['gid'];
                $gr[] = $this->getInfo($gid);
            }
        }
        return $gr;
    }

    /**
     * 获取当前用户所拥有的群组列表 uid为空 返回当前登录用户所拥有的群组列表
     *
     * get api/group/groups
     *
     * 默认每页10条数据，分页结果同评论接口 /api/comment
     *
     * get.type:获取类型  type=1 我加入的所有群(默认)  type=2 我创建的所有群
     *
     * @return array id：群id  name：群名称  uid：群主id  gid：群主guid  des：群描述  img：群logo   （status 0未加入 1已加入 2申请中） time：创建时间  无数据返回为空
     **/
    public function actionGroups()
    {
        $type = (int)Yii::$app->request->get('type');

        if ($this->sync() == true) {
        };
        if (!$type) $type = 1;
        $uid        = Yii::$app->user->id;
        $pagination = new \yii\data\Pagination([
            'defaultPageSize' => 10,
            'validatePage'    => false,
        ]);

        if ($type == 1) {
            $group = GroupUser::find()
                ->select('gid')
                ->where(['uid' => $uid, 'status' => 1])
                ->groupBy('gid')
                ->offset($pagination->offset)->limit($pagination->limit)
                ->all();
            if ($group) {
                foreach ($group as $item) {
                    $gid      = $item['gid'];
                    $groups[] = $this->getInfo($gid);
                }
                return $groups;
            } else {
                return [];
            }
        } else {
            $group = Group::find()
                ->where(['uid' => $uid])
                ->offset($pagination->offset)->limit($pagination->limit)
                ->all();
            if ($group) {
                foreach ($group as $item) {
                    $gid  = $item['id'];
                    $gr[] = $this->getInfo($gid);
                }
                return $gr;
            } else {
                return [];
            }
        }


    }

    /**
     * 添加禁言群成员方法（在 App 中如果不想让某一用户在群中发言时，可将此用户在群组中禁言，被禁言用户可以接收查看群组中用户聊天信息，但不能发送消息。）
     * post api/group/gsg
     *
     * post.guid:用户 guid。（必传）
     *
     * post.gid:群组 Id。（必传）
     *
     * post.minute:禁言时长，以分钟为单位，最大值为43200分钟。（必传）
     *
     * @return boolean
     **/
    public function actionGsg()
    {
        $data = Yii::$app->request->post();
        $res  = $this->ry->group()->addGagUser($data['guid'], $data['gid'], $data['minute']);

        $res = json_decode($res, true);
        if ($res['code'] == 200) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 查询被禁言群成员方法
     *
     * get api/group/gsg-user
     *
     * get.gid:群组Id。（必传）
     *
     * @return array 没有则为空
     **/
    public function actionGsgUser()
    {
        $gid = (int)Yii::$app->request->get('gid');
//return $gid;
        $res = $this->ry->group()->lisGagUser($gid);

        $res = json_decode($res, true);
        return $res['users'];
    }

    /**
     * 移除禁言群成员方法
     *
     * get api/group/del-gsg
     *
     * get.guid:用户guid。支持同时移除多个群成员（必传）
     *
     * get.gid:群组Id。（必传）
     *
     * @return boolean
     **/
    public function actionDelGsg()
    {
        $data = (int)Yii::$app->request->get();

        $res = $this->ry->group()->rollBackGagUser($data['guid'], $data['gid']);

        $res = json_decode($res, true);
        if ($res['code'] == 200) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 推送申请人消息到群管理员  消息类型为  GC:TxtMsg
     *
     * post api/group/publish
     *
     * post.fromUserId:发送人用户 guid（必传）
     *
     * post.toUserId:接收用户 guid（必传）
     *
     * post.txtMessage:发送消息内容（必传）
     *
     * post.gid:群组id（必传）
     *
     * @return boolean 推送信息格式 content：申请原因  extra：群组id
     */
    public function actionPublish()
    {
        $data = Yii::$app->request->post();

        $pd = GroupUser::find()->where(['guid' => $data['fromUserId'], 'gid' => $data['gid']])->one();

        if ($pd) throw new \yii\web\BadRequestHttpException('您已申请加入本群');

        $js = [
            'content' => $data['txtMessage'],
            'extra'   => $data['gid']
        ];

        $content    = json_encode($js);
        $objectName = 'GC:TxtMsg';
        $mes        = $this
            ->ry
            ->message()
            ->PublishSystem($data['fromUserId'], $data['toUserId'], $objectName, $content, $data['txtMessage'], $data['txtMessage'], $data['isPersisted'] = 1, $data['isCounted'] = 1);

        $mes = json_decode($mes, true);
        if ($mes['code'] == 200) {
            $user       = User::findOne(['guid' => $data['fromUserId']]);
            $uid        = $user->id;
            $gu         = new GroupUser();
            $gu->status = 2;
            $gu->guid   = $data['fromUserId'];
            $gu->gid    = $data['gid'];
            $gu->uid    = $uid;
            $gu->save();

            return true;
        } else {
            return false;
        }
    }

    /**
     * 拒绝加群申请 消息类型为  (官方)RC:InfoNtf
     *
     * post api/group/publish-del
     *
     * post.fromUserId:发送人用户 guid（必传）
     *
     * post.toUserId:接收用户 guid（必传）
     *
     * post.gid:群组id（必传）
     *
     * @return boolean 推送信息格式 content：拒绝消息  extra：群组id
     */
    public function actionPublishDel()
    {
        $data = Yii::$app->request->post();
        if ($data['gid']) {
            $gid = $data['gid'];
        } else {
            return 0;
        }
        $guid = $data['toUserId'];
        $gu = GroupUser::find()->where(['gid' => $gid, 'guid' => $guid])->one();
        if ($gu) $gu->delete();

        return true;
          //拒绝消息通知
//        $dd   = Group::findOne($gid);
//        $name = $dd->name;
//
//        $js = [
//            'message' => '抱歉，加入群组' . $name . '申请未通过',
//            'extra'   => $data['gid']
//        ];
//
//        $content    = json_encode($js);
//        $objectName = 'RC:InfoNtf';
//        $mes        = $this
//            ->ry
//            ->message()
//            ->PublishSystem($data['fromUserId'], $data['toUserId'], $objectName, $content, $data['txtMessage'], $data['txtMessage'], $data['isPersisted'] = 1, $data['isCounted'] = 1);
//
//        $mes = json_decode($mes, true);
//        if ($mes['code'] == 200) {
//            $gu = GroupUser::find()->where(['gid' => $gid, 'guid' => $guid])->one();
//            if ($gu) $gu->delete();
//            return true;
//        } else {
//            return false;
//        }
    }

    //群组内消息提示
    private function send($gid,$uid,$type){
        if ($gid){
            $group=Group::findOne($gid);
            $fromUser=$group->guid;

            $data=$this->getProfile($uid);
            $name=$data['username'];
            if ($type==1){
                $js = [
                    'message' =>date('H:i:s',time()).' '. $name . '已加入本群',
                    'extra'   => $gid
                ];
            }else{
                $js = [
                    'message' => date('H:i:s',time()).' ' .$name . '已退出本群',
                    'extra'   => $gid
                ];
            }

            $content    = json_encode($js);
            $objectName = 'RC:InfoNtf';

            $res=$this->ry
                ->message()->publishGroup($fromUser, $gid,  $objectName, $content,$pushContent = '', $pushData = '', 1, 1, 0);
            $mes = json_decode($res, true);
            if ($mes['code'] == 200) {
                return true;
            }else{
                return false;
            }
        }
    }

    //oss上传图片
    protected function handleFileUpload($cFile, $object = null, $guid, $safe = 0)
    {
        $output = array();

        $file       = new FileAli();
        $file->guid = $guid;

        $file->setUploadedFile($cFile);

        if ($object != null) {
            $file->object_id    = $object->getPrimaryKey();
            $file->object_model = $object->className();
        }

        if (!$file->validate()) {
            return false;
        }
        if (($ossurl = $file->oss_up($safe)) === false) {
            return false;
        }
        $file->ossurl = $ossurl;

        if ($file->save()) {
            $output['error']        = false;
            $output['guid']         = $file->guid;
            $output['name']         = $file->file_name;
            $output['title']        = $file->title;
            $output['size']         = $file->size;
            $output['mimeIcon']     = \humhub\libs\MimeHelper::getMimeIconClassByExtension($file->getExtension());
            $output['mimeBaseType'] = $file->getMimeBaseType();
            $output['mimeSubType']  = $file->getMimeSubType();
            $output['url']          = $file->getUrl("", false);
            $output['thumbnailUrl'] = $file->getPreviewImageUrl(400, 400);
        } else {
            $output['error']  = true;
            $output['errors'] = $file->getErrors();
        }

        $output['name']         = $file->file_name;
        $output['size']         = $file->size;
        $output['deleteUrl']    = "";
        $output['deleteType']   = "";
        $output['thumbnailUrl'] = "";

        return $output;
    }

    //获取用户资料（guid）
    private function getProfile($uid = null)
    {
        if ($uid == null) {
            return false;
        }
        $user             = User::findOne(['guid' => $uid]);
        $data['username'] = $user->getDisplayName();
        $data['image']    = $user->getProfileImage()->getUrl();
        $data['guid']     = $uid;
        $data['id']       = $user->id;

        return $data;
    }

    //获取用户资料（id）
    private function getProfile1($uid = null)
    {
        if ($uid == null) {
            return false;
        }
        $user             = User::findOne($uid);
        $data['username'] = $user->getDisplayName();
        $data['image']    = $user->getProfileImage()->getUrl();
        $data['guid']     = $user->guid;
        $data['id']       = $uid;

        return $data;
    }

    //获取群资料
    private function getInfo($gid)
    {
        $group = Group::find()->where(['id' => $gid])->asArray()->one();
        $uid   = $group['uid'];
        $data  = $this->getProfile1($uid);

        $num             = GroupUser::find()->where(['gid' => $gid, 'status' => 1])->asArray()->count();
        $group['status'] = $this->status($gid);
        $group['count']  = $num;
        $group['user']   = $data;
        $group['gid']    = $group['id'];
        return $group;
    }

    //是否加入群状态判断
    private function status($gid)
    {
        $uid = Yii::$app->user->id;
        $pd  = GroupUser::findOne(['gid' => $gid, 'uid' => $uid]);
        if ($pd) {
            $status = $pd->status;
        } else {
            $status = 0;
        }
        return $status;
    }
}

